﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Web;
using ApiPrototype.Handlers;
using ApiPrototype.Models;
using System.Collections.Specialized;
using System.Net.Http;

namespace ApiPrototype.APIs
{
    [ServiceContract]
    public class UpdateApi
    {
        [WebInvoke(Method = "POST"), Authorization, ContentParam(ParamName = "input", ParamType = typeof(UpdateParamDto[]))]
        public ApiResponse<UpdateDto> Post(UpdateParamDto[] input, iphlEntities ctx, int studentId, HttpRequestMessage request)
        {
            var responseData = new UpdateDto();

            foreach (UpdateParamDto p in input)
            {
                switch (p.Type)
                {
                    case "lessenrooster":
                        responseData.Lessenrooster = getLessenroosterUpdate(ctx, studentId, p.LastUpdate);
                        break;
                    case "examenrooster":
                        responseData.Examenrooster = getExamenroosterUpdate(ctx, studentId, p.LastUpdate);
                        break;
                    case "mededelingen":
                        responseData.Mededelingen = getBBMededelingenUpdate(ctx, studentId, p.LastUpdate);
                        break;
                    case "diensten":
                        responseData.Diensten = getDienstenUpdate(ctx, p.LastUpdate);
                        break;
                }
            }

            return new ApiResponse<UpdateDto>(responseData);
        }

        private UpdateDtoEntry<LessenroosterDto> getLessenroosterUpdate(iphlEntities ctx, int id, DateTime date)
        {
            var updates = ctx.SP_UPDATEFOR_LESSENROOSTER(id, date).ToList();

            var delete = from u in updates
                         where u.SUP_ACTION.Equals("delete")
                         select u.PLA_ID;

            var data = new LessenroosterDto();
            data.Planningen = (
                       from u in updates
                       where u.SUP_ACTION.Equals("data")
                       select new PLANNING()
                       {
                           PLA_ID = u.PLA_ID,
                           DOC_ID = u.DOC_ID,
                           OLO_ID = u.OLO_ID,
                           PLA_ACADEMIEJAAR = u.PLA_ACADEMIEJAAR,
                           PLA_KLAS = u.PLA_KLAS,
                           PLA_LOKAAL = u.PLA_LOKAAL,
                           PLA_TOT_DATUM = u.PLA_TOT_DATUM,
                           PLA_TOT_UUR = u.PLA_TOT_UUR,
                           PLA_VAN_DATUM = u.PLA_VAN_DATUM,
                           PLA_VAN_UUR = u.PLA_VAN_UUR,
                           PLA_WEEKDAG = u.PLA_WEEKDAG
                       }
                ).ToList();

            foreach (PLANNING p in data.Planningen)
            {
                if (
                    (
                        from d in data.Docenten
                        where d.DOC_ID == p.DOC_ID
                        select d.DOC_ID
                    ).Count() == 0
                )
                {
                    data.Docenten.Add(ctx.DOCENT.Where(d => d.DOC_ID == p.DOC_ID).FirstOrDefault());
                }

                if (
                    (
                        from o in data.Olods
                        where o.OLO_ID == p.OLO_ID
                        select o.OLO_ID
                    ).Count() == 0
                )
                {
                    data.Olods.Add(ctx.OLOD.Where(o => o.OLO_ID == p.OLO_ID).FirstOrDefault());
                }
            }

            return new UpdateDtoEntry<LessenroosterDto>(delete.ToArray(), data);
        }

        private UpdateDtoEntry<List<SP_EXAMEN_ENTRY>> getExamenroosterUpdate(iphlEntities ctx, int id, DateTime date)
        {
            var updates = ctx.SP_UPDATEFOR_EXAMEN(id, date).ToList();

            var delete = from u in updates
                         where u.SUP_ACTION.Equals("delete")
                         select u.PLA_ID;

            var data = (
                       from u in updates
                       where u.SUP_ACTION.Equals("data")
                       select new SP_EXAMEN_ENTRY()
                       {
                           PLA_ID = u.PLA_ID,
                           STU_ID = u.STU_ID,
                           EXA_BANKKANT = u.EXA_BANKKANT,
                           EXA_EXAMENMOMENT = u.EXA_EXAMENMOMENT,
                           EXA_LOKAAL = u.EXA_LOKAAL,
                           EXA_VOLGNR = u.EXA_VOLGNR,
                           OLO_OMSCHRIJVING = u.OLO_OMSCHRIJVING
                       }
                ).ToList();

            return new UpdateDtoEntry<List<SP_EXAMEN_ENTRY>>(delete.ToArray(), data);
        }

        private UpdateDtoEntry<List<STUDENT_BB_MEDEDELINGEN>> getBBMededelingenUpdate(iphlEntities ctx, int id, DateTime date)
        {
            var updates = ctx.SP_UPDATEFOR_BBMEDEDELINGEN(id, date).ToList();

            var delete = from u in updates
                         where u.SUP_ACTION.Equals("delete")
                         select u.MED_ID;

            var data = (
                       from u in updates
                       where u.SUP_ACTION.Equals("data")
                       select new STUDENT_BB_MEDEDELINGEN()
                       {
                           MED_ID = u.MED_ID,
                           STU_ID = u.STU_ID,
                           OLO_ID = u.OLO_ID,
                           OLO_OMSCHRIJVING = u.OLO_OMSCHRIJVING,
                           MED_BESCHIKBAAR = u.MED_BESCHIKBAAR,
                           MED_DATUM = u.MED_DATUM,
                           MED_INHOUD = u.MED_INHOUD,
                           MED_ONDERWERP = u.MED_ONDERWERP
                       }
                ).ToList();

            return new UpdateDtoEntry<List<STUDENT_BB_MEDEDELINGEN>>(delete.ToArray(), data);
        }

        private UpdateDtoEntry<List<DienstDto>> getDienstenUpdate(iphlEntities ctx, DateTime date)
        {
            List<DienstDto> data = null;

            var updateInfo = ctx.GLOBALUPDATE.Where(gu => gu.GUP_TYPE.Equals("diensten")).FirstOrDefault();
            if(updateInfo == null)
            {
                throw new ApiException(new NullReferenceException("Diensten rij niet teruggevonden bij globale updates."));
            }
            
            if (updateInfo.GUP_LAST_UPDATE > date)
            {
                data = new List<DienstDto>();
                foreach (DIENST d in ctx.DIENST.Include("OPENINGSUUR").ToList())
                {
                    data.Add(new DienstDto() { Dienst = d, Openingsuren = d.OPENINGSUUR });
                }
            }

            return new UpdateDtoEntry<List<DienstDto>>(null, data);
        }
    }
}